package org.cbioportal.legacy.service.impl;

import java.util.ArrayList;
import java.util.List;
import org.cbioportal.legacy.model.GeneFilterQuery;
import org.cbioportal.legacy.model.GenomicDataCountItem;
import org.cbioportal.legacy.model.MolecularProfile;
import org.cbioportal.legacy.model.Mutation;
import org.cbioportal.legacy.model.MutationCountByPosition;
import org.cbioportal.legacy.model.meta.MutationMeta;
import org.cbioportal.legacy.persistence.MutationRepository;
import org.cbioportal.legacy.service.MolecularProfileService;
import org.cbioportal.legacy.service.MutationService;
import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MutationServiceImpl implements MutationService {

  @Autowired private MutationRepository mutationRepository;
  @Autowired private MolecularProfileService molecularProfileService;

  @Override
  public List<Mutation> getMutationsInMolecularProfileBySampleListId(
      String molecularProfileId,
      String sampleListId,
      List<Integer> entrezGeneIds,
      boolean snpOnly,
      String projection,
      Integer pageSize,
      Integer pageNumber,
      String sortBy,
      String direction)
      throws MolecularProfileNotFoundException {

    validateMolecularProfile(molecularProfileId);

    List<Mutation> mutationList =
        mutationRepository.getMutationsInMolecularProfileBySampleListId(
            molecularProfileId,
            sampleListId,
            entrezGeneIds,
            snpOnly,
            projection,
            pageSize,
            pageNumber,
            sortBy,
            direction);

    return mutationList;
  }

  @Override
  public MutationMeta getMetaMutationsInMolecularProfileBySampleListId(
      String molecularProfileId, String sampleListId, List<Integer> entrezGeneIds)
      throws MolecularProfileNotFoundException {

    validateMolecularProfile(molecularProfileId);

    return mutationRepository.getMetaMutationsInMolecularProfileBySampleListId(
        molecularProfileId, sampleListId, entrezGeneIds);
  }

  public List<Mutation> getMutationsInMultipleMolecularProfilesByGeneQueries(
      List<String> molecularProfileIds,
      List<String> sampleIds,
      List<GeneFilterQuery> geneQueries,
      String projection,
      Integer pageSize,
      Integer pageNumber,
      String sortBy,
      String direction) {

    List<Mutation> mutationList =
        mutationRepository.getMutationsInMultipleMolecularProfilesByGeneQueries(
            molecularProfileIds,
            sampleIds,
            geneQueries,
            projection,
            pageSize,
            pageNumber,
            sortBy,
            direction);

    return mutationList;
  }

  @Override
  public List<Mutation> getMutationsInMultipleMolecularProfiles(
      List<String> molecularProfileIds,
      List<String> sampleIds,
      List<Integer> entrezGeneIds,
      String projection,
      Integer pageSize,
      Integer pageNumber,
      String sortBy,
      String direction) {

    List<Mutation> mutationList =
        mutationRepository.getMutationsInMultipleMolecularProfiles(
            molecularProfileIds,
            sampleIds,
            entrezGeneIds,
            projection,
            pageSize,
            pageNumber,
            sortBy,
            direction);

    return mutationList;
  }

  @Override
  public MutationMeta getMetaMutationsInMultipleMolecularProfiles(
      List<String> molecularProfileIds, List<String> sampleIds, List<Integer> entrezGeneIds) {

    return mutationRepository.getMetaMutationsInMultipleMolecularProfiles(
        molecularProfileIds, sampleIds, entrezGeneIds);
  }

  @Override
  public List<Mutation> fetchMutationsInMolecularProfile(
      String molecularProfileId,
      List<String> sampleIds,
      List<Integer> entrezGeneIds,
      boolean snpOnly,
      String projection,
      Integer pageSize,
      Integer pageNumber,
      String sortBy,
      String direction)
      throws MolecularProfileNotFoundException {

    validateMolecularProfile(molecularProfileId);

    List<Mutation> mutationList =
        mutationRepository.fetchMutationsInMolecularProfile(
            molecularProfileId,
            sampleIds,
            entrezGeneIds,
            snpOnly,
            projection,
            pageSize,
            pageNumber,
            sortBy,
            direction);

    return mutationList;
  }

  @Override
  public MutationMeta fetchMetaMutationsInMolecularProfile(
      String molecularProfileId, List<String> sampleIds, List<Integer> entrezGeneIds)
      throws MolecularProfileNotFoundException {

    validateMolecularProfile(molecularProfileId);

    return mutationRepository.fetchMetaMutationsInMolecularProfile(
        molecularProfileId, sampleIds, entrezGeneIds);
  }

  @Override
  public List<MutationCountByPosition> fetchMutationCountsByPosition(
      List<Integer> entrezGeneIds, List<Integer> proteinPosStarts, List<Integer> proteinPosEnds) {

    List<MutationCountByPosition> mutationCountByPositionList = new ArrayList<>();
    for (int i = 0; i < entrezGeneIds.size(); i++) {

      MutationCountByPosition mutationCountByPosition =
          mutationRepository.getMutationCountByPosition(
              entrezGeneIds.get(i), proteinPosStarts.get(i), proteinPosEnds.get(i));
      mutationCountByPositionList.add(mutationCountByPosition);
    }

    return mutationCountByPositionList;
  }

  @Override
  public GenomicDataCountItem getMutationCountsByType(
      List<String> molecularProfileIds,
      List<String> sampleIds,
      List<Integer> entrezGeneIds,
      String profileType) {
    return mutationRepository.getMutationCountsByType(
        molecularProfileIds, sampleIds, entrezGeneIds, profileType);
  }

  private MolecularProfile validateMolecularProfile(String molecularProfileId)
      throws MolecularProfileNotFoundException {

    MolecularProfile molecularProfile =
        molecularProfileService.getMolecularProfile(molecularProfileId);

    if (!(molecularProfile
            .getMolecularAlterationType()
            .equals(MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED)
        || molecularProfile
            .getMolecularAlterationType()
            .equals(MolecularProfile.MolecularAlterationType.MUTATION_UNCALLED))) {

      throw new MolecularProfileNotFoundException(molecularProfileId);
    }

    return molecularProfile;
  }
}
